/**
 * Copyright 2014 the original author or authors. All rights reserved.
 */
package com.visionet.security.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.visionet.jumper.core.domain.bean.Page;
import com.visionet.jumper.core.domain.search.HqlSearchable;
import com.visionet.jumper.core.domain.search.Searchable;
import com.visionet.jumper.core.domain.search.SqlSearchable;
import com.visionet.jumper.core.service.impl.AbstractBaseService;
import com.visionet.security.service.SecurityResourceService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.visionet.security.domain.entity.Resource;
import com.visionet.security.domain.dto.UrlizedResource;
import com.visionet.security.repository.SecurityResourceRepository;
import com.visionet.security.base.enums.ResourceType;

/**
 * 
 *
 * @author suxiaojing
 * @date 
 * @since 0.0.1
 */
@Service
@Transactional
public class SecurityResourceServiceImpl extends AbstractBaseService<Resource>
		implements SecurityResourceService {
	
	@javax.annotation.Resource
	private SecurityResourceRepository securityResourceRepository;


	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<UrlizedResource> getMenu() {
		List<Resource> resourceList = securityResourceRepository.findByTypeAndIsDeleted(ResourceType.MENU, false);
		return generateMenuList(resourceList);
	}

	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<UrlizedResource> getMenu(Integer level) {
		List<Resource> resourceList = securityResourceRepository.findByTypeAndLevel(
				ResourceType.MENU, level);
		return generateMenuList(resourceList);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.visionet.platform.components.security.service.ResourceService#getMenu
	 * (java.lang.String)
	 */
	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<UrlizedResource> getMenu(String parentId) {
		// No implement yet
		return null;
	}

	private List<UrlizedResource> packingUserMenu(List<UrlizedResource> menuList) {
		Map<String, UrlizedResource> menuMap = new HashMap<>();
		List<UrlizedResource> removeList = new ArrayList<>();
		for (UrlizedResource menu : menuList) {
			if (StringUtils.isNotEmpty(menu.getParentId())) {
				UrlizedResource parentMenu = menuMap.get(String.format("%s_%s", menu.getParentId(),
						menu.getLevel() - 1));
				boolean mergeable = mergeMap(menuMap,
						String.format("%s_%s", menu.getId(), menu.getLevel()), menu);
				if (!mergeable) {
					parentMenu.getSubResource().add(menu);
				}
				removeList.add(menu);
			} else {
				boolean mergeable = mergeMap(menuMap,
						String.format("%s_%s", menu.getId(), menu.getLevel()), menu);
				if (mergeable) {
					removeList.add(menu);
				}
			}
		}
		menuList.removeAll(removeList);
		return menuList;
	}

	private boolean mergeMap(Map<String, UrlizedResource> menuMap, String key,
			UrlizedResource resource) {
		UrlizedResource menu = menuMap.get(key);
		if (menu != null) {
			menu.setPermission(String.format("%s,%s", menu.getPermission(),
					resource.getPermission()));
			return true;
		} else {
			menuMap.put(key, resource);
			return false;
		}
	}

	private List<UrlizedResource> generateMenuList(List<Resource> resourceList) {
		if (CollectionUtils.isEmpty(resourceList)) {
			return null;
		}
		List<UrlizedResource> menuList = new ArrayList<>();
		for (Resource resource : resourceList) {
			UrlizedResource menu = new UrlizedResource();
			menu.from(resource);
			if(resource.getParent() != null) {
				menu.setParentId(resource.getParent().getId());
			}
			menuList.add(menu);
		}
		return menuList;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.visionet.platform.components.security.service.ResourceService# getCurrentUserMenu()
	 */
	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<UrlizedResource> getCurrentUserMenu() {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.visionet.platform.components.security.service.ResourceService#
	 * getCurrentUserMenu(java.lang.Integer)
	 */
	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<UrlizedResource> getCurrentUserMenu(Integer level) {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.visionet.platform.components.security.service.ResourceService#
	 * getCurrentUserMenu(java.lang.String)
	 */
	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<UrlizedResource> getCurrentUserMenu(String parentId) {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.visionet.platform.components.security.service.ResourceService# getUrlizedResource()
	 */
	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<UrlizedResource> getUrlizedResource() {
		List<ResourceType> typeList = new ArrayList<>();
		typeList.add(ResourceType.MENU);
		typeList.add(ResourceType.PATH);
		List<Resource> resourceList = securityResourceRepository.getUrlizedResource(typeList);
		return generateMenuList(resourceList);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.visionet.platform.components.security.service.ResourceService#getUserMenu(java.lang.String
	 * )
	 */
	@Override
	public List<UrlizedResource> getUserMenu(String userId) {
		List<UrlizedResource> resourceList = securityResourceRepository.getUserMenu(userId);
		return packingUserMenu(resourceList);
	}

	@Override
	public Page getMenuForPage(Page page) {
		return securityResourceRepository.getMenuForPage(page);
	}
}
